package com.onpositive.wiki3.catmodels;

import java.util.HashMap;
import java.util.HashSet;

import com.onpositive.nlp.inflector.English;
import com.onpositive.nlp.sequence.ClassifiedSequence;
import com.onpositive.nlp.sequence.ClassifiedSequence.Token;
import com.onpositive.nlp.sequence.SequenceParser;
import com.onpositive.nlp.sequence.WikiLookup;
import com.onpositive.wiki3.db.catmodel.Category;
import com.onpositive.wiki3.db.catmodel.ICategoryMatcher;
import com.onpositive.wiki3.db.catmodel.matches.classify.AbstractRecordingMatcher;
import com.onpositive.wiki3.db.catmodel.matches.classify.RelationConstants;
import com.onpositive.wiki3.db.catmodel.matches.classify.RelationStore;

import edu.smu.tspell.wordnet.Synset;
import edu.smu.tspell.wordnet.SynsetType;
import edu.smu.tspell.wordnet.WordNetDatabase;

public class ModelBasedRelationBuilder extends AbstractRecordingMatcher
		implements ICategoryMatcher {

	public ModelBasedRelationBuilder(RelationStore store) {
		super(store);
	}

	static HashSet<String> allowedClassifators = new HashSet<String>();

	static {
		allowedClassifators.add("by");

		// allowedClassifators.add("in");
	}

	@Override
	public int accept(Category st) {
		ICategoryModel model = ModelTagger.getModel(st);

		if (model != null && !model.isPossibleCategorization(st)) {
			// this is not categorization;
			return 0;
		}
		Category[] childCategories = st.getChildCategories();

		if (childCategories.length == 0) {
			return 0;
		}
		ClassifiedSequence core = getCore(st);
		if (model instanceof ClassificatorCategoryModel) {
			if (core.isClassification()) {
				String classificator = core.getClassificator();
				boolean in = false;
				if (classificator.equals("in")) {
					Category[] parentsCategories = st.getParentsCategories();
					for (Category c : parentsCategories) {
						if (c.getSequnce().isClassification()) {
							in = true;
						}
					}
				}
				if (allowedClassifators.contains(classificator)) {
					in = true;
				}
				if (in) {
					for (Category c : childCategories) {
						record(RelationConstants.IS_A, st, c);
					}
				}
			}
		}
		String string = st.toString();

		if (core != null) {
			Token core2 = core.getCore();
			if (core2 != null) {

				string = core2.name;
				while (string.indexOf('_') != -1) {
					ClassifiedSequence parse = SequenceParser.parse(string,
							new WikiLookup(string, st.getStore().getDb()
									.getTitleMapper()));
					if (parse.getCore() != null) {
						string = parse.getCore().name;
					} else {
						break;

					}
				}
			}
		}

		for (Category c : childCategories) {
			ICategoryModel cgmodel = ModelTagger.getModel(c);
			if (cgmodel instanceof ClassificatorCategoryModel
					&& !(model instanceof ClassificatorCategoryModel)) {
				ClassifiedSequence sequnce = c.getSequnce();
				String classificator = sequnce.getClassificator();
				if (classificator == null || !classificator.equals("by")) {
					continue;
				}
			}
			if (cgmodel != null) {

				String primaryParentForm = cgmodel.getPrimaryParentForm(c);
				if (primaryParentForm == null) {
					continue;
				}
				if (primaryParentForm.indexOf('_') != -1) {
					primaryParentForm = primaryParentForm
							.substring(primaryParentForm.lastIndexOf('_') + 1);
				}
				if (primaryParentForm != null) {

					if (primaryParentForm.equals(string)) {
						record(RelationConstants.IS_A, st, c);
						continue;
					} else {
						Synset[] synsets = getSynsets(primaryParentForm);
						l2: for (Synset s : synsets) {

							for (String q : s.getWordForms()) {

								if (string.contains(q)&&!string.endsWith("ing")) {

									record(RelationConstants.IS_A, st, c);
									break l2;
								}

								String plural = English.plural(q);
								if (string.equals(plural)) {
									record(RelationConstants.IS_A, st, c);
									break l2;
								}
							}
						}
						continue;
					}
				}

			}
		}
		// TODO Auto-generated method stub
		return 0;
	}

	HashMap<String, Synset[]> sets = new HashMap<String, Synset[]>();

	protected Synset[] getSynsets(String primaryParentForm) {
		if (sets.containsKey(primaryParentForm)) {
			return sets.get(primaryParentForm);
		}
		Synset[] synsets = WordNetDatabase.getFileInstance().getSynsets(
				primaryParentForm, SynsetType.NOUN);
		sets.put(primaryParentForm, synsets);
		return synsets;
	}
}
